﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web.Mvc;
using WebStickyNotes.Contracts;
using WebStickyNotes.Contracts.Interfaces;
using WebStickyNotes.Data.Access;
using WebStickyNotes.Helpers;
using WebStickyNotes.Models;
using WebStickyNotes.Resources;
using System.Linq;

namespace WebStickyNotes.Controllers
{
    public class TaskDetailController : Controller
    {
        private readonly string _connectionType;
        private readonly string _connectionString;
        private readonly int _pageSize;

        private static readonly List<int> AllowedTaskRoleId = new List<int> { 1, 2 };

        public TaskDetailController()
        {
            _connectionType = ConfigurationManager.AppSettings["ConnectionType"];
            _connectionString = ConfigurationManager.ConnectionStrings["WebStickyNotesData"].ConnectionString;
            _pageSize = int.Parse(ConfigurationManager.AppSettings["PageSize"]);
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult Index(int? page)
        {
            var pageNumber = PagingHelper.GetPageNumber(page);

            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var results = FilteredDataHelper.GetFilteredTaskDetailsForUser(supplier.DataAccess, currentUser, supplier.DataAccess.GetAllTaskDetails());
                var resultPage = PagingHelper.GetPageOfResults(results, _pageSize, pageNumber);

                var model = new TaskDetailIndexModel
                {
                    TotalRecords = results.Count,
                    CurrentPage = pageNumber,
                    PageSize = _pageSize,
                    PagingLink = string.Format("{0}?page={1}", Request.Url.AbsolutePath, "{0}"),
                    TaskDetails = FilteredDataHelper.GetExtendedTaskDetails(supplier.DataAccess, resultPage),
                    CurrentUser = currentUser
                };

                return View(model);
            }
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult TasksForStream(int id, int? page)
        {
            var pageNumber = PagingHelper.GetPageNumber(page);

            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var results = FilteredDataHelper.GetFilteredTaskDetailsForUser(supplier.DataAccess, currentUser, supplier.DataAccess.GetTasksByStream(id));
                var resultPage = PagingHelper.GetPageOfResults(results, _pageSize, pageNumber);

                var model = new TaskDetailIndexModel
                {
                    TotalRecords = results.Count,
                    CurrentPage = pageNumber,
                    PageSize = _pageSize,
                    PagingLink = string.Format("{0}?page={1}", Request.Url.AbsolutePath, "{0}"),
                    TaskDetails = FilteredDataHelper.GetExtendedTaskDetails(supplier.DataAccess, resultPage),
                    CurrentUser = currentUser
                };

                return View("Index", model);
            }
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult TasksForProject(int id, int? page)
        {
            var pageNumber = PagingHelper.GetPageNumber(page);

            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var results = FilteredDataHelper.GetFilteredTaskDetailsForUser(supplier.DataAccess, currentUser, supplier.DataAccess.GetTasksByProject(id));
                var resultPage = PagingHelper.GetPageOfResults(results, _pageSize, pageNumber);

                var model = new TaskDetailIndexModel
                {
                    TotalRecords = results.Count,
                    CurrentPage = pageNumber,
                    PageSize = _pageSize,
                    PagingLink = string.Format("{0}?page={1}", Request.Url.AbsolutePath, "{0}"),
                    TaskDetails = FilteredDataHelper.GetExtendedTaskDetails(supplier.DataAccess, resultPage),
                    CurrentUser = currentUser
                };

                return View("Index", model);
            }
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult TasksForPerson(int id, int? page)
        {
            var pageNumber = PagingHelper.GetPageNumber(page);

            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var results = FilteredDataHelper.GetFilteredTaskDetailsForUser(supplier.DataAccess, currentUser, supplier.DataAccess.GetTasksByPerson(id));
                var resultPage = PagingHelper.GetPageOfResults(results, _pageSize, pageNumber);

                var model = new TaskDetailIndexModel
                {
                    TotalRecords = results.Count,
                    CurrentPage = pageNumber,
                    PageSize = _pageSize,
                    PagingLink = string.Format("{0}?page={1}", Request.Url.AbsolutePath, "{0}"),
                    TaskDetails = FilteredDataHelper.GetExtendedTaskDetails(supplier.DataAccess, resultPage),
                    CurrentUser = currentUser
                };

                return View("Index", model);
            }
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult TodoList(int id, int? page)
        {
            var pageNumber = PagingHelper.GetPageNumber(page);

            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var results = FilteredDataHelper.GetFilteredTaskDetailsForUser(supplier.DataAccess, currentUser, supplier.DataAccess.GetTasksByPerson(id));

                results = results.Where(r => r.PercentageComplete < 100).ToList();

                var resultPage = PagingHelper.GetPageOfResults(results, _pageSize, pageNumber);

                var model = new TaskDetailIndexModel
                {
                    TotalRecords = results.Count,
                    CurrentPage = pageNumber,
                    PageSize = _pageSize,
                    PagingLink = string.Format("{0}?page={1}", Request.Url.AbsolutePath, "{0}"),
                    TaskDetails = FilteredDataHelper.GetExtendedTaskDetails(supplier.DataAccess, resultPage),
                    CurrentUser = currentUser
                };

                return View("Index", model);
            }
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult TaskDetailSearch(string searchTerm, int? page)
        {
            var pageNumber = PagingHelper.GetPageNumber(page);

            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());

                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var results = FilteredDataHelper.GetFilteredTaskDetailsForUser(supplier.DataAccess, currentUser, supplier.DataAccess.GetTasksForSearch(searchTerm));
                var resultPage = PagingHelper.GetPageOfResults(results, _pageSize, pageNumber);

                var model = new TaskDetailIndexModel
                {
                    TotalRecords = results.Count,
                    CurrentPage = pageNumber,
                    PageSize = _pageSize,
                    SearchTerm = searchTerm,
                    PagingLink = string.Format("{0}?searchTerm={1}&page={2}", Request.Url.AbsolutePath, searchTerm, "{0}"),
                    TaskDetails = FilteredDataHelper.GetExtendedTaskDetails(supplier.DataAccess, resultPage),
                    CurrentUser = currentUser
                };

                return View("Index", model);
            }
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult Add()
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var model = new EditTaskDetailModel
                                {
                                    Task = new TaskDetail
                                               {
                                                   MilestoneDate = DateTime.Today
                                               },
                                    Message = new Message()
                                };

                PopulatePageLabels(model, supplier.DataAccess, currentUser);


                return View("Edit", model);
            }
        }

        [HttpPost]
        [MustSignIn]
        public ActionResult Add(EditTaskDetailModel model)
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                ValidateEditTaskDetailModel(model);

                if (ModelState.IsValid)
                {
                    var addSuccessModel = new AddSuccessModel
                                              {
                                                  Id = supplier.DataAccess.SaveTaskDetail(model.Task),
                                                  Action = "Edit",
                                                  Controller = "TaskDetail",
                                                  ViewItems = Labels.Tasks,
                                                  ViewAction = "TaskDetails",
                                                  Message = new Message
                                                                {
                                                                    Class = "okay",
                                                                    Text = Labels.SavedOkay
                                                                }
                                              };

                    // Audit
                    AuditHelper.AuditAction(supplier.DataAccess, "Add", model.Task, currentUser.Id);

                    // ReSharper disable Asp.NotResolved
                    return View(addSuccessModel);
                    // ReSharper restore Asp.NotResolved
                }

                model.Message = new Message { Text = Labels.PleaseCorrectErrors, Class = "error" };

                PopulatePageLabels(model, supplier.DataAccess, currentUser);

                return View("Edit", model);
            }
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult Edit(int id)
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var taskDetail = supplier.DataAccess.GetTaskDetail(id).Task;

                var model = new EditTaskDetailModel
                                {
                                    Task = taskDetail,
                                    Message = new Message()
                                };

                PopulatePageLabels(model, supplier.DataAccess, currentUser);

                return View(model);
            }
        }

        [HttpPost]
        [MustSignIn]
        public ActionResult Edit(EditTaskDetailModel model)
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                ValidateEditTaskDetailModel(model);

                if (ModelState.IsValid)
                {
                    supplier.DataAccess.SaveTaskDetail(model.Task);
                    model.Message = new Message { Text = Labels.SavedOkay, Class = "okay" };

                    // Audit
                    AuditHelper.AuditAction(supplier.DataAccess, "Edit", model.Task, currentUser.Id);
                }
                else
                {
                    model.Message = new Message { Text = Labels.PleaseCorrectErrors, Class = "error" };
                }

                PopulatePageLabels(model, supplier.DataAccess, currentUser);

                return View(model);
            }
        }

        [HttpGet]
        [MustSignIn]
        public JsonResult MoveTask(int taskId, int streamId)
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return Json(new object(), JsonRequestBehavior.AllowGet);
                }

                var taskDetail = supplier.DataAccess.GetTaskDetail(taskId).Task;

                taskDetail.TaskStreamId = streamId;

                supplier.DataAccess.SaveTaskDetail(taskDetail);

                // Audit
                AuditHelper.AuditAction(supplier.DataAccess, "Move", taskDetail, currentUser.Id);

                return Json(taskDetail, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpGet]
        [MustSignIn]
        public JsonResult UpdateProgress(int taskId, int progress)
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return Json(new object(), JsonRequestBehavior.AllowGet);
                }

                var taskDetail = supplier.DataAccess.GetTaskDetail(taskId).Task;

                taskDetail.PercentageComplete = progress;

                supplier.DataAccess.SaveTaskDetail(taskDetail);

                // Audit
                AuditHelper.AuditAction(supplier.DataAccess, "Progress", taskDetail, currentUser.Id);

                return Json(taskDetail, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult AjaxEdit(int id)
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var taskDetail = supplier.DataAccess.GetTaskDetail(id).Task;

                var model = new EditTaskDetailModel
                {
                    Task = taskDetail
                };

                PopulatePageLabels(model, supplier.DataAccess, currentUser);

                return View(model);
            }
        }

        [HttpPost]
        [MustSignIn]
        public ActionResult AjaxEdit(EditTaskDetailModel model)
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                ValidateEditTaskDetailModel(model);

                if (ModelState.IsValid)
                {
                    supplier.DataAccess.SaveTaskDetail(model.Task);
                    model.Message = new Message { Text = Labels.SavedOkay, Class = "okay" };

                    // Audit
                    AuditHelper.AuditAction(supplier.DataAccess, "Edit", model.Task, currentUser.Id);

                    var taskStream = supplier.DataAccess.GetTaskStream(model.Task.TaskStreamId);

                    return RedirectToAction("ViewProject", "Home", new { id = taskStream.TaskProjectId });
                }

                model.Message = new Message { Text = Labels.PleaseCorrectErrors, Class = "error" };
                PopulatePageLabels(model, supplier.DataAccess, currentUser);
                return View(model);
            }
        }

        [HttpGet]
        [MustSignIn]
        public ActionResult Delete(int id)
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var model = new DeleteTaskDetailModel
                                {
                                    Task = supplier.DataAccess.GetTaskDetail(id),
                                    ShowButton = true,
                                    Message = new Message
                                                  {
                                                      Text = Labels.TextAreYouSureYouWantToDelete,
                                                      Class = "error"
                                                  }
                                };

                return View(model);
            }
        }

        [HttpPost]
        [MustSignIn]
        public ActionResult Delete(bool confirm, int id)
        {
            using (var supplier = new Supplier(_connectionType, _connectionString))
            {
                var currentUser = supplier.DataAccess.GetTaskPerson(SecurityHelper.GetSignedInUserId());
                if (!AllowedTaskRoleId.Contains(currentUser.TaskRoleId))
                {
                    return RedirectToAction("AccessDenied", "Home", new { address = HttpContext.Request.Url.AbsoluteUri });
                }

                var model = new DeleteTaskDetailModel
                {
                    Task = supplier.DataAccess.GetTaskDetail(id),
                    ShowButton = false,
                    Message = new Message
                                  {
                                      Text = Labels.DeletedOkay,
                                      Class = "okay"
                                  }
                };

                supplier.DataAccess.DeleteTaskDetail(id);

                // Audit
                AuditHelper.AuditAction(supplier.DataAccess, "Delete", model.Task.Task, currentUser.Id);

                return View(model);
            }
        }

        private static void PopulatePageLabels(EditTaskDetailModel model, IWebStickyNotesDataAccess dataAccess, TaskPerson currentUser)
        {
            // Drop Down Lists
            model.TaskStreams = FilteredDataHelper.GetFilteredTaskStreamsForUser(dataAccess, currentUser);
            model.TaskPeople = dataAccess.GetAllTaskPeople();
            model.TaskPriorities = dataAccess.GetAllTaskPriorities();
        }

        private void ValidateEditTaskDetailModel(EditTaskDetailModel model)
        {
            if (string.IsNullOrEmpty(model.Task.Title))
            {
                ModelState.AddModelError("Task.Title", Labels.PleaseEnterTitle);
            }

            if (string.IsNullOrEmpty(model.Task.Description))
            {
                model.Task.Description = string.Empty;
            }
        }
    }
}